package com.youlai.boot.modules.webapp.service.impl;

import com.youlai.boot.common.exception.BusinessException;
import com.youlai.boot.common.result.ResultCode;
import com.youlai.boot.modules.webapp.config.HivisionIdPhotoConfig;
import com.youlai.boot.modules.webapp.service.IdPhotoService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Slf4j
@Service
@RequiredArgsConstructor
public class IdPhotoServiceImpl implements IdPhotoService {

    private final HivisionIdPhotoConfig config;
    private final RestTemplate restTemplate;

    public Map<String, Object> generateIdPhoto(MultipartFile image, String spec) {
        try {
            File tempFile = convertMultipartFileToFile(image);

            // 调用HivisionIDPhotos API
            MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
            parts.add("input_image", new FileSystemResource(tempFile));
            if (spec != null && !spec.isEmpty()) {
                parts.add("spec", spec);
            }

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.MULTIPART_FORM_DATA);

            HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(parts, headers);

            ResponseEntity<byte[]> response = restTemplate.postForEntity(
                    config.getIdPhotoUrl(),
                    requestEntity,
                    byte[].class
            );

            // 将图片转换为Base64
            String base64Image = Base64.getEncoder().encodeToString(response.getBody());

            // 清理临时文件
            tempFile.delete();

            // 构建与原API格式一致的响应
            Map<String, Object> result = new HashMap<>();
            result.put("status", true);
            result.put("image_base64_hd", base64Image);  // 高清版本
            result.put("image_base64_standard", base64Image);  // 标准版本

            return result;
        } catch (Exception e) {
            log.error("生成证件照失败", e);
            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("status", false);
            errorResult.put("message", "生成证件照失败: " + e.getMessage());
            return errorResult;
        }
    }

    /**
     * 将文件上传到系统文件服务
     *
     * @param file     要上传的文件
     * @param fileName 文件名
     * @return 文件访问URL
     */
    private String uploadFileToSystem(File file, String fileName) {
        try {
            // 调用系统文件上传API
            String uploadUrl = "http://localhost:8989/dev-api/api/v1/files";

            MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
            parts.add("file", new FileSystemResource(file));

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.MULTIPART_FORM_DATA);

            HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(parts, headers);

            ResponseEntity<Map> response = restTemplate.postForEntity(
                    uploadUrl,
                    requestEntity,
                    Map.class
            );

            if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                Map<String, Object> responseData = response.getBody();

                // 根据系统文件上传API的响应格式提取URL
                if ("00000".equals(responseData.get("code"))) {
                    Map<String, String> data = (Map<String, String>) responseData.get("data");
                    return data.get("url");
                } else {
                    log.error("文件上传失败: {}", responseData);
                    throw new BusinessException(ResultCode.SYSTEM_EXECUTION_ERROR.getCode(), "文件上传失败");
                }
            } else {
                log.error("文件上传响应异常: {}", response);
                throw new BusinessException(ResultCode.SYSTEM_EXECUTION_ERROR.getCode(), "文件上传响应异常");
            }
        } catch (Exception e) {
            log.error("上传文件到文件服务失败", e);
            throw new BusinessException(ResultCode.SYSTEM_EXECUTION_ERROR.getCode(), "上传文件到文件服务失败: " + e.getMessage());
        }
    }

    @Override
    public Map<String, Object> addBackground(MultipartFile image, String color) {
        try {
            File tempFile = convertMultipartFileToFile(image);

            MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
            parts.add("input_image", new FileSystemResource(tempFile));
            parts.add("color", color);
            parts.add("dpi", "300");
            parts.add("render", "0");

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.MULTIPART_FORM_DATA);

            HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(parts, headers);

            ResponseEntity<byte[]> response = restTemplate.postForEntity(
                    config.getAddBackgroundUrl(),
                    requestEntity,
                    byte[].class
            );

            // 将图片转换为Base64
            String base64Image = Base64.getEncoder().encodeToString(response.getBody());

            tempFile.delete();

            // 构建与原API格式一致的响应
            Map<String, Object> result = new HashMap<>();
            result.put("status", true);
            result.put("image_base64", base64Image);  // 高清版本
            return result;
        } catch (Exception e) {
            log.error("添加背景失败", e);
            throw new BusinessException(ResultCode.SYSTEM_EXECUTION_ERROR.getCode(), "添加背景失败: " + e.getMessage());
        }
    }

    @Override
    public String humanMatting(MultipartFile image) {
        try {
            File tempFile = convertMultipartFileToFile(image);

            MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
            parts.add("input_image", new FileSystemResource(tempFile));

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.MULTIPART_FORM_DATA);

            HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(parts, headers);

            ResponseEntity<byte[]> response = restTemplate.postForEntity(
                    config.getHumanMattingUrl(),
                    requestEntity,
                    byte[].class
            );

            String fileName = saveResponseImage(response.getBody(), "matting_");

            tempFile.delete();

            return fileName;
        } catch (Exception e) {
            log.error("人像抠图失败", e);
            throw new BusinessException(ResultCode.SYSTEM_EXECUTION_ERROR.getCode(), "人像抠图失败: " + e.getMessage());
        }
    }

    @Override
    public void setPhotoSpec(Map<String, Object> spec) {
        try {
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);

            HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(spec, headers);

            restTemplate.postForEntity(
                    config.getSetKbUrl(),
                    requestEntity,
                    String.class
            );
        } catch (Exception e) {
            log.error("设置证件照规格失败", e);
            throw new BusinessException(ResultCode.SYSTEM_EXECUTION_ERROR.getCode(), "设置证件照规格失败: " + e.getMessage());
        }
    }

    @Override
    public String generateLayoutPhotos(MultipartFile image, String layout) {
        try {
            File tempFile = convertMultipartFileToFile(image);

            MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
            parts.add("input_image", new FileSystemResource(tempFile));
            parts.add("layout", layout);

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.MULTIPART_FORM_DATA);

            HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(parts, headers);

            ResponseEntity<byte[]> response = restTemplate.postForEntity(
                    config.getGenerateLayoutPhotosUrl(),
                    requestEntity,
                    byte[].class
            );
            // 调用dev-api/api/v1/files 这个接口 上传文件
            // 返回文件路径
            // 删除临时文件
            // 返回文件路径

            return null;
        } catch (Exception e) {
            log.error("生成排版照片失败", e);
            throw new BusinessException(ResultCode.SYSTEM_EXECUTION_ERROR.getCode(), "生成排版照片失败: " + e.getMessage());
        }
    }

    @Override
    public String addWatermark(MultipartFile image, String text) {
        try {
            File tempFile = convertMultipartFileToFile(image);

            MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
            parts.add("input_image", new FileSystemResource(tempFile));
            parts.add("text", text);

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.MULTIPART_FORM_DATA);

            HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(parts, headers);

            ResponseEntity<byte[]> response = restTemplate.postForEntity(
                    config.getWatermarkUrl(),
                    requestEntity,
                    byte[].class
            );

            String fileName = saveResponseImage(response.getBody(), "watermark_");

            tempFile.delete();

            return fileName;
        } catch (Exception e) {
            log.error("添加水印失败", e);
            throw new BusinessException(ResultCode.SYSTEM_EXECUTION_ERROR.getCode(), "添加水印失败: " + e.getMessage());
        }
    }

    @Override
    public String idPhotoCrop(MultipartFile image, Integer x, Integer y, Integer width, Integer height) {
        try {
            File tempFile = convertMultipartFileToFile(image);

            MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
            parts.add("input_image", new FileSystemResource(tempFile));
            parts.add("x", x.toString());
            parts.add("y", y.toString());
            parts.add("width", width.toString());
            parts.add("height", height.toString());

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.MULTIPART_FORM_DATA);

            HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(parts, headers);

            ResponseEntity<byte[]> response = restTemplate.postForEntity(
                    config.getIdPhotoCropUrl(),
                    requestEntity,
                    byte[].class
            );

            String fileName = saveResponseImage(response.getBody(), "crop_");

            tempFile.delete();

            return fileName;
        } catch (Exception e) {
            log.error("证件照裁剪失败", e);
            throw new BusinessException(ResultCode.SYSTEM_EXECUTION_ERROR.getCode(), "证件照裁剪失败: " + e.getMessage());
        }
    }

    /**
     * 将MultipartFile转换为File
     */
    private File convertMultipartFileToFile(MultipartFile file) throws IOException {
        File convertedFile = new File(System.getProperty("java.io.tmpdir") + "/" + file.getOriginalFilename());
        file.transferTo(convertedFile);
        return convertedFile;
    }

    /**
     * 保存响应的图片数据
     */
    private String saveResponseImage(byte[] imageData, String prefix) throws IOException {
        // 创建上传目录
        String dateDir = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        String uploadDir = System.getProperty("user.dir") + config.getUploadPath() + dateDir;
        Path dirPath = Paths.get(uploadDir);
        if (!Files.exists(dirPath)) {
            Files.createDirectories(dirPath);
        }

        // 生成文件名
        String fileName = prefix + UUID.randomUUID().toString().replace("-", "") + ".jpg";
        Path filePath = Paths.get(uploadDir, fileName);

        // 保存文件
        Files.write(filePath, imageData);

        // 返回文件访问路径
        return config.getUploadPath() + dateDir + "/" + fileName;
    }
} 